﻿/*
 * Author: Roy Scheefhals
 * 
 * Description: Makes a Fourier transform out of the white or black pixels in an image
 * 
 * NOT IMPLEMENTED
 * */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
namespace LibraryCS
{
    public class Fourier : VisionAlgorithm
    {
        int percToUse;
        public Fourier(String name)
            : base(name)
        {
        }

        public override System.Drawing.Bitmap DoAlgorithm(System.Drawing.Bitmap sourceImage)
        {

  //          String templateDir = "..\\..\\..\\Resources\\FontSets\\";
            VImage VInput = new VImage(sourceImage);
            byte[] grayinput = VInput.GrayPixels;

            int N = VInput.Height * VInput.Width;
            double p = 0;

            Complex[] fourier = new Complex[VInput.Width * VInput.Height];
            
            Complex[] output = new Complex[VInput.Width * VInput.Height];
            
            for (int y = 0; y < VInput.Height; y++)
            {
                for (int x = 0; x < VInput.Width; x++)
                {
                    fourier[y * VInput.Width + x] = new Complex((double)grayinput[y * VInput.Width + x], 0);
                    
                    output[y * VInput.Width + x] = new Complex((double)grayinput[y * VInput.Width + x], 0);
                }
            }
            

            int amountBoundaries = 0;
            int amountN;
            
            for (int y = 0; y < VInput.Height; y++)
            {
                for (int x = 0; x < VInput.Width; x++)
                {
                    // find the amount of boundary points
                    if (grayinput[(y * VInput.Width) + x] == 0)
                    {
                        amountBoundaries++;
                    }
                }
            }

            amountN = (amountBoundaries /100) * percToUse;

            Debug.WriteLine("amount of boundaries: " + amountN);

            Complex[] Fu = new Complex[amountN];
            

            for (int m = 0; m < amountN; m++)
            {
                Fu[m] = new Complex();
                for ( int k =0; k < amountN ; k++){
                    p = (2*Math.PI * m *k )/amountN; 
                
                    Fu[m].real += fourier[k].real * Math.Cos(p) + fourier[k].imag * Math.Sin(p);

                    Fu[m].imag += fourier[k].imag * Math.Cos(p) - fourier[k].real * Math.Sin(p);
                }
                Fu[m].real /= amountN;
                Fu[m].imag /= amountN;
            }


            for (int i = 0; i < amountN; i++)
            {
                Fu[i].calcMag();
            }


            Debug.WriteLine("Fourier done");
            /*double a;
            for (int y = 0; y < N; y++)
            {
                for (int x = 0; x < N; x++)
                {
                    p = (2 * Math.PI * y * x) / N;
                    // Real
                    //a = fourier[x].real * Math.Cos(p);
                    //a = a + fourier[x].imag * Math.Sin(p);
                    //Fu[y].real = a;
                    Fu[y].real += fourier[x].real * Math.Cos(p) + fourier[x].imag * Math.Sin(p);
                    //imaginary
                    Fu[y].imag += fourier[x].imag * Math.Cos(p) - fourier[x].real * Math.Sin(p);
                }
                Fu[y].real /= N;
                Fu[y].imag /= N;
            }
            Debug.WriteLine("Done with fourier");
            /*         fourier[y * VInput.Width + x].real = grayinput[y * VInput.Width + x];
                     fourier[y * VInput.Width + x].imag = 0;

                     output[y * VInput.Width + x].real = grayinput[y * VInput.Width + x];
                     output[y * VInput.Width + x].imag = 0;
                 }
             }


             // got the real and imaginary complex data
             // the N is in the case of an image the amount of pixels 
             Nx = VInput.Width;
             Ny = VInput.Height;
             int m; // power of 2 for current no of points
             // Transform the Rows 
             double[]real = new double[Nx];
             double[] imag = new double[Nx];

             for (int y = 0; y < Ny; y++) // main for loop
             {
                 for (int x = 0; x < Nx; x++)
                 {
                     real[x] = fourier[y * Nx + x].real;
                     imag[x] = fourier[y * Nx + x].imag;
                 }

                 m = (int)Math.Log(Nx, 2); //Finding power of 2 for current number of points e.g. for nx=512 m=9
                
             }*/

            return sourceImage;
        }

        #region GUI Functions
        public override List<Control> createControls()
        {
            List<Control> Controls = new List<Control>();

            // Create a Label indictating the type of setting this is
            Label lb = new Label();
            lb.AutoSize = true;
            lb.Text = "% to check";
            lb.Name = "lbFourier";

            // Create a TextBox Control for setting the percentage of noise
            TextBox tb = new TextBox();
            tb.Name = "tbFourier";
            tb.AcceptsReturn = false;
            tb.MaxLength = 3;
            tb.Multiline = false;
            tb.Size = new Size(50, 25);

            // Add the controls to the list
            Controls.Add(tb);
            Controls.Add(lb);

            // Return the list
            return Controls;
        }

        /* 
         * Toegevoegd door: Duncan Jenkins
        */
        public override void setSettings(List<object> settings)
        {
            percToUse = Int32.Parse(((TextBox)settings[0]).Text);
            Debug.WriteLine("Settings entered: " + percToUse);
        }
        #endregion
    }
}
